package org.liaohailong.library.widget.shopping.adapter;

import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.liaohailong.library.widget.shopping.ShoppingListView;
import org.liaohailong.library.widget.shopping.helper.ShoppingRange;
import org.liaohailong.library.widget.shopping.observable.IDataObservable;
import org.liaohailong.library.widget.shopping.observable.IShoppingDataObserver;

import java.util.ArrayList;
import java.util.List;

/**
 * Author: Victor
 * E-mail: liaohailong190@foxmail.com
 * Date: 2019/6/22 14:57
 * Description: 电商平台列表适配器
 */
public class ShoppingAdapter<VH extends ShoppingViewHolder> implements IShoppingAdapter<VH>, IDataObservable {

    private int itemCount;
    private ArrayList<ShoppingRange> ranges = new ArrayList<>();

    private ArrayList<ShoppingSectionAdapter<VH>> sectionAdapters = new ArrayList<>();

    private IShoppingDataObserver dataObserver;

    public void setSectionAdapters(@NonNull List<ShoppingSectionAdapter<VH>> adapters) {
        for (ShoppingSectionAdapter<VH> sectionAdapter : sectionAdapters) {
            sectionAdapter.setDataObserver(null);
        }
        sectionAdapters.clear();
        sectionAdapters.addAll(adapters);

        calculateAdapters();

        /*
         * 注册数据观察者，改变后回调
         * */
        for (int i = 0; i < sectionAdapters.size(); i++) {
            ShoppingSectionAdapter<VH> sectionAdapter = sectionAdapters.get(i);

            final int index = i;
            sectionAdapter.setDataObserver(new IShoppingDataObserver() {

                @Override
                public void onItemRangeChanged(int position, int count) {
                    int positionOffset = getPositionLessOffset(index);
                    int absolutePosition = positionOffset + position;
                    notifyItemRangeChanged(absolutePosition, count);
                }

                @Override
                public void onItemRangeInserted(int position, int count) {
                    int positionOffset = getPositionLessOffset(index);
                    int absolutePosition = positionOffset + position;
                    notifyItemRangeInserted(absolutePosition, count);
                }

                @Override
                public void onItemRangeRemoved(int position, int count) {
                    int positionOffset = getPositionLessOffset(index);
                    int absolutePosition = positionOffset + position;
                    notifyItemRangeRemoved(absolutePosition, count);
                }
            });
        }
    }

    private void calculateAdapters() {
        itemCount = 0;
        ranges.clear();
        int startPosition;
        int endPosition = 0;

        for (ShoppingSectionAdapter sectionAdapter : sectionAdapters) {
            int sectionAdapterItemCount = sectionAdapter.getItemCount();
            itemCount += sectionAdapterItemCount;
            startPosition = endPosition + 1;
            endPosition = startPosition + sectionAdapterItemCount - 1;
            ranges.add(new ShoppingRange(startPosition, endPosition));
        }
    }

    public ArrayList<ShoppingSectionAdapter<VH>> getSectionAdapters() {
        return sectionAdapters;
    }

    @Override
    public int getItemCount() {
        return itemCount;
    }

    @NonNull
    @Override
    public ShoppingItemViewType getItemViewType(int position) {
        ShoppingSectionAdapter sectionAdapter = getSectionAdapterByPosition(position);
        int sectionPosition = position - getPositionMoreOffset(position);
        if (sectionAdapter != null) {
            ShoppingItemViewType itemViewType = sectionAdapter.getItemViewType(sectionPosition);
            return new ShoppingItemViewType(position, itemViewType.getViewType());
        }
        throw new IllegalStateException("ShoppingAdapter.getSectionAdapterByPosition = null ?");
    }

    private ShoppingSectionAdapter<VH> getSectionAdapterByPosition(int position) {
        for (int i = 0; i < ranges.size(); i++) {
            ShoppingRange shoppingRange = ranges.get(i);
            if (shoppingRange.contains(position)) {
                return sectionAdapters.get(i);
            }
        }
        return null;
    }

    public int getAdapterIndexByPosition(int absolutePosition) {
        ShoppingSectionAdapter<VH> sectionAdapter = getSectionAdapterByPosition(absolutePosition);
        return sectionAdapters.indexOf(sectionAdapter);
    }

    private int getPositionMoreOffset(int position) {
        int positionOffset = 0;
        for (ShoppingRange range : ranges) {
            if (range.getEndPosition() < position) {
                positionOffset += range.getRangeSize();
            }
        }
        return positionOffset;
    }

    private int getPositionLessOffset(int adapterIndex) {
        int positionOffset = 0;
        for (int i = 0; i < adapterIndex; i++) {
            ShoppingRange shoppingRange = ranges.get(i);
            positionOffset += shoppingRange.getRangeSize();
        }
        return positionOffset;
    }

    @NonNull
    @Override
    public VH onCreateViewHolder(@NonNull ViewGroup parent, @NonNull ShoppingItemViewType viewType) {
        ShoppingSectionAdapter<VH> sectionAdapter = getSectionAdapterByPosition(viewType.getPosition());
        if (sectionAdapter != null) {
            VH viewHolder = sectionAdapter.onCreateViewHolder(parent, viewType);
            viewHolder.setViewType(viewType);
            ShoppingListView.LayoutParams layoutParams = (ShoppingListView.LayoutParams) viewHolder.getItemView().getLayoutParams();
            layoutParams.setViewHolder(viewHolder);
            return viewHolder;
        }
        throw new IllegalStateException("ShoppingAdapter.getSectionAdapterByPosition = null ?");
    }

    @Override
    public void onBindViewHolder(@NonNull VH viewHolder, int position, @Nullable Object payLoad) {
        int sectionPosition = position - getPositionMoreOffset(position);
        ShoppingSectionAdapter<VH> sectionAdapter = getSectionAdapterByPosition(position);
        ShoppingItemViewType viewType = viewHolder.getViewType();
        viewType.setPosition(position);

        if (sectionAdapter != null) {
            sectionAdapter.onBindViewHolder(viewHolder, sectionPosition, payLoad);
        }
    }

    @Override
    public void setDataObserver(IShoppingDataObserver observer) {
        dataObserver = observer;
    }

    @Override
    public IShoppingDataObserver getDataObserver() {
        return dataObserver;
    }

    @Override
    public void notifyDataSetChanged() {
        getDataObserver().onItemRangeChanged(0, itemCount);
    }

    @Override
    public void notifyItemRangeChanged(int position, int count) {
        getDataObserver().onItemRangeChanged(position, count);
    }

    @Override
    public void notifyItemRangeInserted(int position, int count) {
        getDataObserver().onItemRangeInserted(position, count);
    }

    @Override
    public void notifyItemRangeRemoved(int position, int count) {
        getDataObserver().onItemRangeRemoved(position, count);
    }
}
